﻿//        Copyright (c) 2010, Semyon A. Chertkov (semyonc@gmail.com)
//        All rights reserved.
//
//        This program is free software: you can redistribute it and/or modify
//        it under the terms of the GNU General Public License as published by
//        the Free Software Foundation, either version 3 of the License, or
//        any later version.

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.Common;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Threading;
using ICSharpCode.AvalonEdit.Highlighting;

using DataEngine;
using DataEngine.CoreServices;
using DataEngine.Export;



namespace XQueryConsole
{
    /// <summary>
    /// Interaction logic for CreateTableDialog.xaml
    /// </summary>
    public partial class CreateTableDialog : Window, INotifyPropertyChanged 
    {
        private readonly string sTableUnspec = "(Not all data specified)";

        private Connection dataSource;
        private string tableName;
        private bool autoGenerateDDL;
        private string cachedDDL;
        private DispatcherTimer dispatcherTimer;

        public CreateTableDialog(bool flatTable)
        {
            InitializeComponent();
            CommandText = sTableUnspec;
            MainWindow main = (MainWindow)Application.Current.MainWindow;
            List<Connection> connections = new List<Connection>();
            foreach (Connection conn in main.DatasourceController.Container.connections)
                if (flatTable || conn.Accessor == AccessorType.MongoDb)
                    connections.Add(conn);
            DataContext = connections;
            BatchMove = new BatchMove();
            AutoGenerateDDL = true;
            dispatcherTimer = new DispatcherTimer();
            dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, 300);
            dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
        }

        private void dispatcherTimer_Tick(object sender, EventArgs e)
        {
            dispatcherTimer.Stop();
            if (DataSource == null)
                return;
            BatchMove.Accessor = DataSource.Accessor;
            BatchMove.ProviderInvariantName = DataSource.InvariantName;
            BatchMove.ConnectionString = DataSource.ConnectionString;
            BatchMove.X86Connection = DataSource.X86Connection;
            Cursor = Cursors.Wait;
            try
            {
                try
                {
                    switch (DataSource.Accessor)
                    {
                        case AccessorType.DataProvider:
                            cachedDDL = BatchMove.GetCreateTableDDL();
                            textEditor.SyntaxHighlighting = HighlightingManager.Instance.GetDefinition("SQLX");
                            break;

                        case AccessorType.MongoDb:
                            textEditor.SyntaxHighlighting = HighlightingManager.Instance.GetDefinition("JavaScript");
#if JS
                            CommandText = BsonFormatter.CreateJavascriptTemplate(BatchMove.Source.RowType);
#endif
                            break;

                        default:
                            MessageBox.Show(this, "This datasource is not supported", "Information",
                                MessageBoxButton.OK, MessageBoxImage.Information);
                            return;
                    }
                    if (AutoGenerateDDL && !String.IsNullOrEmpty(TableName))
                    {
                        BatchMove.TableName = TableName;
                        CreateCommandText();
                        if (BatchMove.HasUnknownDatatype)
                            MessageBox.Show(this, "Table definition has datatypes not supported by selected provider", "Information",
                                MessageBoxButton.OK, MessageBoxImage.Information);
                    }

                }
                catch (Exception ex)
                {
                    MessageBox.Show(this, ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
            finally
            {
                Cursor = null;
            }
        }

        private void CreateCommandText()
        {
            BatchMove.TableName = TableName;
            if (!String.IsNullOrEmpty(TableName) && DataSource != null)
                switch (DataSource.Accessor)
                {
                    case AccessorType.DataProvider:
                        {
                            DataProviderHelper helper = new DataProviderHelper(DataSource.InvariantName,
                                DataSource.ConnectionString, DataSource.X86Connection);
                            CommandText = String.Format("CREATE TABLE {0} (\n{1}\n)",
                                helper.FormatIdentifier(Util.SplitName(TableName)), cachedDDL);
                        }
                        break;

#if !JS
                    case AccessorType.MongoDb:
                        CommandText = String.Format("db.createCollection('{0}');", TableName);
                        break;
#endif
                }
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        #endregion

        public Connection DataSource
        {
            get
            {
                return dataSource;
            }
            set
            {
                dataSource = value;
                dispatcherTimer.Start();
                OnPropertyChanged("DataSource");
                OnPropertyChanged("IsOkButtonEnabled");
            }
        }

        public string TableName 
        {
            get
            {
                return tableName;
            }
            set
            {
                tableName = value;
                CreateCommandText();
                OnPropertyChanged("TableName");
                OnPropertyChanged("IsOkButtonEnabled");
            }
        }

        public string CommandText 
        {
            get
            {
                return textEditor.Document.Text;
            }
            set
            {
                textEditor.Document.Text = value;
                OnPropertyChanged("CommandText");
            }
        }

        public bool AutoGenerateDDL 
        {
            get
            {
                return autoGenerateDDL;
            }
            set
            {
                if (value != autoGenerateDDL)
                {
                    autoGenerateDDL = value;
                    textEditor.IsReadOnly = autoGenerateDDL;
                    OnPropertyChanged("AutoGenerateDDL");
                }
            }
        }

        public bool IsOkButtonEnabled
        {
            get
            {
                return DataSource != null && !String.IsNullOrEmpty(TableName);
            }
        }

        public BatchMove BatchMove { get; private set; }

        private void okButton_Click(object sender, RoutedEventArgs e)
        {
            if (DataSource != null)
            {
                BatchMove.DML = CommandText;
                if (BatchMove.IsTableExists())
                {
                    if (MessageBox.Show(String.Format("The table {0} is already exists on database server.\r\n" +
                        "Do you want to drop existing table ?", TableName), "Confirmation", MessageBoxButton.OKCancel, MessageBoxImage.Information) == MessageBoxResult.OK &&
                        MessageBox.Show("All table data will be lost !\r\nContinue ?", "Warning", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes)
                        BatchMove.DropTable();
                }
                if (DataSource.Accessor == AccessorType.DataProvider)
                {
                    DataProviderHelper helper = new DataProviderHelper(DataSource.InvariantName,
                        DataSource.ConnectionString, DataSource.X86Connection);
                    using (DbConnection conn = DataProviderHelper.CreateDbConnection(DataSource.InvariantName, DataSource.X86Connection))
                    {
                        conn.ConnectionString = DataSource.ConnectionString;
                        DbCommand command = conn.CreateCommand();
                        command.CommandText = CommandText;
                        conn.Open();
                        try
                        {
                            command.ExecuteNonQuery();
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(this, ex.Message, "SQL Error",
                                MessageBoxButton.OK, MessageBoxImage.Error);
                            return;
                        }
                        conn.Close();
                    }
                    if (!autoGenerateDDL)
                    {
                        MainWindow main = (MainWindow)Application.Current.MainWindow;
                        DatabaseDictionary dict = main.DatasourceController.Dictionary;
                        TableType tableType = dict.GetTableType(DataSource.Prefix,
                            Util.SplitName(BatchMove.TableName), null);
                        BatchMove.SetFieldsFromTableType(tableType);
                    }
                }
                DialogResult = true;
            }
        }
    }
}
